import Redis from 'ioredis';
import {
  QuestionService,
  ScoringService,
  AnalyticsService,
  DifficultyConfig,
  ScoringConfig,
  AnalyticsConfig,
  CacheConfig,
  BaseService
} from '../types/services';
import { QuestionServiceImpl } from './questionService';
import { ScoringServiceImpl } from './scoringService';
import { AnalyticsServiceImpl } from './analyticsService';
import { config } from '../config/serviceConfig';
import { errorHandler } from '../utils/errorHandler';

type ServiceType = 'question' | 'scoring' | 'analytics';
type ServiceInstance = QuestionService | ScoringService | AnalyticsService;

export class ServiceFactory {
  private static instance: ServiceFactory;
  private redis: Redis;
  private services: Map<ServiceType, ServiceInstance>;
  private isShuttingDown: boolean;

  private constructor() {
    this.redis = new Redis(config.redis);
    this.services = new Map();
    this.isShuttingDown = false;
    this.setupRedisErrorHandling();
  }

  static getInstance(): ServiceFactory {
    if (!ServiceFactory.instance) {
      ServiceFactory.instance = new ServiceFactory();
    }
    return ServiceFactory.instance;
  }

  // 获取问题服务实例
  getQuestionService(customConfig?: {
    difficultyConfig?: Partial<DifficultyConfig>;
    cacheConfig?: Partial<CacheConfig>;
  }): QuestionService {
    this.checkShutdownStatus();
    const serviceType: ServiceType = 'question';

    if (!this.services.has(serviceType)) {
      this.services.set(serviceType, new QuestionServiceImpl(
        this.redis,
        {
          ...config.difficulty,
          ...customConfig?.difficultyConfig
        },
        {
          ...config.cache.question,
          ...customConfig?.cacheConfig
        }
      ));
    }

    return this.services.get(serviceType) as QuestionService;
  }

  // 获取评分服务实例
  getScoringService(customConfig?: {
    scoringConfig?: Partial<ScoringConfig>;
    cacheConfig?: Partial<CacheConfig>;
  }): ScoringService {
    this.checkShutdownStatus();
    const serviceType: ServiceType = 'scoring';

    if (!this.services.has(serviceType)) {
      this.services.set(serviceType, new ScoringServiceImpl(
        this.redis,
        {
          ...config.scoring,
          ...customConfig?.scoringConfig
        },
        {
          ...config.cache.scoring,
          ...customConfig?.cacheConfig
        }
      ));
    }

    return this.services.get(serviceType) as ScoringService;
  }

  // 获取分析服务实例
  getAnalyticsService(customConfig?: {
    analyticsConfig?: Partial<AnalyticsConfig>;
    cacheConfig?: Partial<CacheConfig>;
  }): AnalyticsService {
    this.checkShutdownStatus();
    const serviceType: ServiceType = 'analytics';

    if (!this.services.has(serviceType)) {
      this.services.set(serviceType, new AnalyticsServiceImpl(
        this.redis,
        {
          ...config.analytics,
          ...customConfig?.analyticsConfig
        },
        {
          ...config.cache.analytics,
          ...customConfig?.cacheConfig
        }
      ));
    }

    return this.services.get(serviceType) as AnalyticsService;
  }

  // 获取Redis实例
  getRedis(): Redis {
    this.checkShutdownStatus();
    return this.redis;
  }

  // 关闭所有服务和连接
  async shutdown(): Promise<void> {
    if (this.isShuttingDown) {
      return;
    }

    this.isShuttingDown = true;
    console.log('Shutting down services...');

    try {
      // 并行执行所有服务的清理
      const cleanupPromises = Array.from(this.services.values()).map(async service => {
        try {
          if (service.cleanup) {
            await service.cleanup();
          } else if (service.stop) {
            service.stop();
          }
        } catch (error) {
          errorHandler.handleError(error instanceof Error ? error : new Error('Service cleanup failed'));
        }
      });

      await Promise.all(cleanupPromises);

      // 清理服务映射
      this.services.clear();

      // 关闭Redis连接
      if (this.redis) {
        await this.redis.quit();
      }

      console.log('All services shut down successfully');
    } catch (error) {
      errorHandler.handleError(error instanceof Error ? error : new Error('Shutdown failed'));
      throw error;
    } finally {
      this.isShuttingDown = false;
    }
  }

  // 重置工厂（主要用于测试）
  async reset(): Promise<void> {
    await this.shutdown();
    ServiceFactory.instance = new ServiceFactory();
  }

  // 检查所有服务的健康状态
  async healthCheck(): Promise<Record<ServiceType, boolean>> {
    const health: Record<ServiceType, boolean> = {
      question: false,
      scoring: false,
      analytics: false
    };

    try {
      // 检查Redis连接
      await this.redis.ping();

      // 并行检查所有服务
      const checks = Array.from(this.services.entries()).map(async ([type, service]) => {
        try {
          health[type] = await service.healthCheck();
        } catch (error) {
          errorHandler.handleError(error instanceof Error ? error : new Error(`Health check failed for ${type}`));
          health[type] = false;
        }
      });

      await Promise.all(checks);
    } catch (error) {
      errorHandler.handleError(error instanceof Error ? error : new Error('Health check failed'));
    }

    return health;
  }

  private setupRedisErrorHandling(): void {
    this.redis.on('error', (error) => {
      console.error('Redis error:', error);
      errorHandler.handleError(error);
      if (config.env.isProduction) {
        this.notifyMonitoring('redis_error', error);
      }
    });

    this.redis.on('connect', () => {
      console.log('Redis connected');
    });

    this.redis.on('ready', () => {
      console.log('Redis ready');
    });

    this.redis.on('reconnecting', () => {
      console.log('Redis reconnecting');
    });
  }

  private checkShutdownStatus(): void {
    if (this.isShuttingDown) {
      throw new Error('Service factory is shutting down');
    }
  }

  private notifyMonitoring(event: string, error: Error): void {
    // TODO: 实现监控通知逻辑
    console.error(`[Monitoring] ${event}:`, error);
  }
}

// 导出单例实例
export const serviceFactory = ServiceFactory.getInstance();

// 确保在进程退出时进行清理
process.on('SIGTERM', async () => {
  console.log('SIGTERM signal received');
  try {
    await serviceFactory.shutdown();
    process.exit(0);
  } catch (error) {
    console.error('Error during shutdown:', error);
    process.exit(1);
  }
});

process.on('SIGINT', async () => {
  console.log('SIGINT signal received');
  try {
    await serviceFactory.shutdown();
    process.exit(0);
  } catch (error) {
    console.error('Error during shutdown:', error);
    process.exit(1);
  }
});

// 处理未捕获的异常和拒绝
process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  errorHandler.handleError(error);
  if (config.env.isProduction) {
    void serviceFactory.shutdown()
      .finally(() => process.exit(1));
  }
});

process.on('unhandledRejection', (reason: unknown) => {
  const error = reason instanceof Error ? reason : new Error(String(reason));
  console.error('Unhandled Rejection:', error);
  errorHandler.handleError(error);
  if (config.env.isProduction) {
    void serviceFactory.shutdown()
      .finally(() => process.exit(1));
  }
});
